import { h } from "vue";
import { List } from "./list";
import { nextTick } from "vue";
import type {
    interGroupControl, interGroupMenu, interGroupMessage, interGroupMessageInfo, interGroupMessageInfoChange,
    UserInfo, groupType, interGroupInfo, interGroupList, interMessageType,
} from './type'

import { Icon, showImagePreview, Uploader, Image, type UploaderFileListItem } from "vant";
import { ElIcon, ElImage, ElUpload, type UploadFile } from "element-plus";
import { Picture } from "@element-plus/icons-vue";

export class GroupList extends List<interGroupInfo> {
    types: { [key in interMessageType]?: interGroupList };
    titles: { [key in groupType]: { color: string, text: string } };
    constructor() {
        super()
        this.url.page = '/vv/group/notReadgroupList'
        this.titles = { C2C: { color: 'var(--el-color-primary, var(--van-primary-color))', text: '1v1会话' } }
        this.types = {
            text: { formatter: (msg) => msg },
            img: { formatter: () => '[图片]' },
            delete: { formatter: () => '[已撤回]' }
        }
    }
    setTypes(types: { [key in interMessageType]?: interGroupList }) {
        Object.assign(this.types, types)
    }
    async delete(index: number) {
        const { groupName } = this.list[index]
        const res = await this.request("/vv/group/delete", { parames: { id: groupName } })
        if (res) {
            this.list.splice(index, 1)
            this.total--
            return true
        }
        return false
    }
}


export class GroupForm extends List<interGroupMessageInfo> {
    message: string
    type: interMessageType
    newMessage: number
    timer: number
    notReadUser: string;
    messages: { [key in interMessageType]?: interGroupMessage };
    menus: { [key: string]: interGroupMenu }
    controls: { [key: string]: interGroupControl }
    canNotBack: interMessageType[];
    placeholder: string
    declare search_key: { groupName: string }
    onNewMessage?: (msg: interGroupMessageInfoChange[]) => void
    constructor() {
        super()
        this.message = ''
        this.type = 'text'
        this.newMessage = 0
        this.notReadUser = ''
        this.canNotBack = ['delete']
        this.url.page = "/vv/group/history"
        this.url.delete = "/vv/group/back"
        this.placeholder = "请输入要发送的内容"
        this.timer = 0
        this.controls = {
            back: {
                show: ({ isSelf, type }) => isSelf && !this.canNotBack.includes(type),
                formatter: (item, index) => h('span', {
                    className: 'textbutton', onClick: () => {
                        this.back(index)
                    }
                }, '撤回')
            },
            back2: {
                show: ({ isSelf, type }) => !isSelf || this.canNotBack.includes(type),
                formatter: () => h('span', { className: 'textbutton', style: "color: #ccc;cursor: default;" }, '撤回')
            }
        }
        this.menus = {
            img: {
                formatter: () => h(ElUpload, {
                    className: 'textbutton', autoUpload: false, showFileList: false,
                    onChange: (file) => this.onChooseImg(file)
                }, { default: () => h(ElIcon, { title: '选择图片' }, { default: () => h(Picture) }) }),
                p_formatter: () => h(Uploader, {
                    className: 'textbutton', showUpload: false,
                    afterRead: (file) => {
                        if (Array.isArray(file)) file = file[0]
                        this.onChooseImg(file)
                    }
                }, {
                    default: () => h(Icon, { name: 'photo-o' })
                })
            }
        }
        this.messages = {
            text: {
                formatter: (msg) => h('div', {}, msg),
                p_formatter: (msg) => h('div', {}, msg)
            },
            img: {
                formatter: (msg) => h(ElImage, { src: msg, previewSrcList: [msg] }),
                p_formatter: (msg) => h(Image, {
                    src: msg, onClick: () => {
                        showImagePreview([msg])
                    }
                })
            },
            delete: {
                formatter: () => h('div', { style: 'font-size: 0.8em;color: #aaa;' }, '消息已撤回'),
                p_formatter: () => h('div', { style: 'font-size: 0.8em;color: #aaa;' }, '消息已撤回')
            }
        }
    }
    messageChange(message: string) {
        this.message = message
    }
    setMessages(messages: { [key in interMessageType]?: interGroupList }) {
        Object.assign(this.messages, messages)
    }
    setMenus(menus: { [key: string]: interGroupMenu }) {
        Object.assign(this.menus, menus)
    }
    setControls(controls: { [key: string]: interGroupControl }) {
        Object.assign(this.controls, controls)
    }
    scrollIntoBottom() {
        document.getElementById('groupInput')?.scrollIntoView(false)
        this.newMessage = 0
    }
    onChooseImg(file: UploaderFileListItem | UploadFile) {
        const File = (file as UploaderFileListItem).file || (file as UploadFile).raw
        if (File) {
            this.type = 'img'
            this.message = URL.createObjectURL(File)
            this.sendMessage()
        }
    }
    checkedScrollBottom(e: Event | { target: HTMLDivElement }) {
        GroupForm.utils_debounce(() => {
            const { scrollTop, clientHeight, scrollHeight } = e.target as HTMLDivElement
            if (scrollTop + clientHeight === scrollHeight) {
                this.newMessage = 0
            }
        }, 500)
    }
    beforeSend(): string | undefined { return undefined }
    afterSend() { }
    async sendMessage() {
        const { type } = this
        let message = this.message
        const id = this.search_key.groupName
        if (type === 'img') {
            message = await this.imgUpload(message)
        }
        const reMessage = this.beforeSend()
        if (reMessage) message = reMessage
        if (!message) return
        const res = await this.request('/vv/group/addMessage', { data: { id, msg: message, type } })
        if (res) {
            this.afterSend()
            this.beforeSend = () => undefined
            this.afterSend = () => { }
            this.type = 'text'
            this.message = ''
            this.list.push({ ...res, isSelf: 1, MessageChanged: true })
            this.total++
            await nextTick()
            this.scrollIntoBottom()
        }
    }
    async getNewMessage() {
        clearTimeout(this.timer)
        const groupName = this.search_key.groupName
        const { total, limit } = this
        const res: { changed: interGroupMessageInfoChange[], otherChanged: UserInfo[] } = await this.request('/vv/group/newMessage', { data: { groupName, offset: total, limit }, unLoadding: true })
        if (res) {
            const { changed, otherChanged } = res
            if (changed.length) {
                if (this.onNewMessage) this.onNewMessage(changed)
                changed.forEach((element) => {
                    requestIdleCallback(() => {
                        if (element.type === 'add') {
                            this.list.push(element.message)
                            this.total++
                            this.newMessage++
                        } else if (element.type === 'back') {
                            const index = this.list.findIndex(item => item.id === element.message.id)
                            this.list.splice(index, 1, element.message)
                        }
                    })
                });
            }
            this.notReadUser = otherChanged.map(item => item.nickname).splice(0, 6).join(',')
            this.timer = setTimeout(() => {
                this.getNewMessage()
            }, 3000)
        }
    }
    async back(index: number) {
        const item = this.list[index]
        const res = await this.request(this.url.delete, { method: 'POST', parames: { id: item.id } })
        if (res) {
            this.list[index].type = "delete"
            return true
        }
        item.show = false
    }
    removeImg() {
        this.message = ''
        this.type = 'text'
    }
}